package com.imut.lagain.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imut.lagain.common.Result;
import com.imut.lagain.entity.MenstrualCycle;
import com.imut.lagain.service.MenstrualCycleService;
import com.imut.lagain.util.JwtUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生理期管理控制器
 */
@RestController
@RequestMapping("/menstrual-cycles")
public class MenstrualCycleController {
    private static final Logger log = LoggerFactory.getLogger(MenstrualCycleController.class);
    
    @Autowired
    private MenstrualCycleService menstrualCycleService;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId(HttpServletRequest request) {
        String authorization = request.getHeader("Authorization");
        if (authorization != null && authorization.startsWith("Bearer ")) {
            String token = authorization.substring(7);
            return jwtUtil.getUserIdFromToken(token);
        }
        throw new RuntimeException("无效的token");
    }
    
    /**
     * 创建生理期记录
     */
    @PostMapping
    public Result<MenstrualCycle> createCycle(@Valid @RequestBody MenstrualCycle cycle, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            MenstrualCycle created = menstrualCycleService.createCycle(cycle, userId);
            return Result.success(created);
        } catch (Exception e) {
            log.error("创建生理期记录失败", e);
            return Result.error("创建生理期记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新生理期记录
     */
    @PutMapping("/{id}")
    public Result<MenstrualCycle> updateCycle(@PathVariable Long id, @Valid @RequestBody MenstrualCycle cycle, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            cycle.setId(id);
            MenstrualCycle updated = menstrualCycleService.updateCycle(cycle, userId);
            return Result.success(updated);
        } catch (Exception e) {
            log.error("更新生理期记录失败", e);
            return Result.error("更新生理期记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除生理期记录
     */
    @DeleteMapping("/{id}")
    public Result<Boolean> deleteCycle(@PathVariable Long id, HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean success = menstrualCycleService.deleteCycle(id, userId);
            return Result.success(success);
        } catch (Exception e) {
            log.error("删除生理期记录失败", e);
            return Result.error("删除生理期记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取用户的生理期记录列表
     */
    @GetMapping
    public Result<IPage<MenstrualCycle>> getUserCycles(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Page<MenstrualCycle> pageParam = new Page<>(page, size);
            IPage<MenstrualCycle> result = menstrualCycleService.getUserCycles(userId, pageParam);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取生理期记录列表失败", e);
            return Result.error("获取生理期记录列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据日期范围获取生理期记录
     */
    @GetMapping("/range")
    public Result<List<MenstrualCycle>> getCyclesByDateRange(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            List<MenstrualCycle> cycles = menstrualCycleService.getCyclesByDateRange(userId, startDate, endDate);
            return Result.success(cycles);
        } catch (Exception e) {
            log.error("根据日期范围获取生理期记录失败", e);
            return Result.error("获取生理期记录失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取指定日期的生理期状态
     */
    @GetMapping("/status")
    public Result<Map<String, Object>> getCycleStatusByDate(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Map<String, Object> status = menstrualCycleService.getCycleStatusByDate(userId, date);
            return Result.success(status);
        } catch (Exception e) {
            log.error("获取生理期状态失败", e);
            return Result.error("获取生理期状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 预测未来的生理期
     */
    @GetMapping("/predictions")
    public Result<List<MenstrualCycle>> predictFutureCycles(
            @RequestParam(defaultValue = "6") int months,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            List<MenstrualCycle> predictions = menstrualCycleService.predictFutureCycles(userId, months);
            return Result.success(predictions);
        } catch (Exception e) {
            log.error("预测未来生理期失败", e);
            return Result.error("预测未来生理期失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取生理期统计信息
     */
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getCycleStatistics(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Map<String, Object> statistics = menstrualCycleService.getCycleStatistics(userId);
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取生理期统计信息失败", e);
            return Result.error("获取生理期统计信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取月度日历数据
     */
    @GetMapping("/calendar")
    public Result<Map<String, Object>> getMonthlyCalendarData(
            @RequestParam int year,
            @RequestParam int month,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Map<String, Object> calendarData = menstrualCycleService.getMonthlyCalendarData(userId, year, month);
            return Result.success(calendarData);
        } catch (Exception e) {
            log.error("获取月度日历数据失败", e);
            return Result.error("获取月度日历数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 记录症状
     */
    @PostMapping("/symptoms")
    public Result<Boolean> recordSymptoms(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            @RequestBody Map<String, Object> symptoms,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean success = menstrualCycleService.recordSymptoms(userId, date, symptoms);
            return Result.success(success);
        } catch (Exception e) {
            log.error("记录症状失败", e);
            return Result.error("记录症状失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取下次预计生理期日期
     */
    @GetMapping("/next-predicted")
    public Result<LocalDate> getNextPredictedDate(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            LocalDate nextDate = menstrualCycleService.getNextPredictedDate(userId);
            return Result.success(nextDate);
        } catch (Exception e) {
            log.error("获取下次预计生理期日期失败", e);
            return Result.error("获取下次预计生理期日期失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取排卵期预测
     */
    @GetMapping("/ovulation")
    public Result<Map<String, Object>> getOvulationPrediction(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            Map<String, Object> ovulation = menstrualCycleService.getOvulationPrediction(userId);
            return Result.success(ovulation);
        } catch (Exception e) {
            log.error("获取排卵期预测失败", e);
            return Result.error("获取排卵期预测失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新周期长度
     */
    @PutMapping("/cycle-length")
    public Result<Boolean> updateCycleLength(
            @RequestParam Integer cycleLength,
            HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean success = menstrualCycleService.updateCycleLength(userId, cycleLength);
            return Result.success(success);
        } catch (Exception e) {
            log.error("更新周期长度失败", e);
            return Result.error("更新周期长度失败: " + e.getMessage());
        }
    }
    
    /**
     * 刷新预测数据
     */
    @PostMapping("/refresh-predictions")
    public Result<Boolean> refreshPredictions(HttpServletRequest request) {
        try {
            Long userId = getCurrentUserId(request);
            boolean success = menstrualCycleService.refreshPredictions(userId);
            return Result.success(success);
        } catch (Exception e) {
            log.error("刷新预测数据失败", e);
            return Result.error("刷新预测数据失败: " + e.getMessage());
        }
    }
}